-- scope_module.vhd

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity scope_module is
	port (
		avs_s0_address     : in  std_logic_vector(7 downto 0)  := (others => '0'); --    s0.address
		avs_s0_read        : in  std_logic                     := '0';             --      .read
		avs_s0_readdata    : out std_logic_vector(31 downto 0);                    --      .readdata
		avs_s0_write       : in  std_logic                     := '0';             --      .write
		avs_s0_writedata   : in  std_logic_vector(31 downto 0) := (others => '0'); --      .writedata
		avs_s0_waitrequest : out std_logic;                                        --      .waitrequest
		clk                : in  std_logic                     := '0';             -- clock.clk
		reset              : in  std_logic                     := '0';             -- reset.reset
		ins_irq0_irq       : out std_logic;                                        --  irq0.irq
		cha_data           : in  std_logic_vector(7 downto 0);
		chb_data           : in  std_logic_vector(7 downto 0);
		adc_clk            : out std_logic;
		cha_fifo_rdreq     : in  std_logic;
		cha_fifo_rdempty   : out std_logic;
		cha_fifo_data      : out std_logic_vector(15 downto 0);
		chb_fifo_rdreq     : in  std_logic;
		chb_fifo_rdempty   : out std_logic;
		chb_fifo_data      : out std_logic_vector(15 downto 0)
	); 
end entity scope_module;
  
architecture rtl of scope_module is
signal scope_current_state:std_logic_vector(7 downto 0);
signal trigger_mode:std_logic_vector(1 downto 0);
signal trigger_voltage_level:std_logic_vector(7 downto 0);
signal clk_div_factor:std_logic_vector(5 downto 0);
signal trigger_source:std_logic;
signal trigger_position:std_logic_vector(12 downto 0);
signal auto_trigger:std_logic;
signal start_sample_cpu,start_sample_ff1,start_sample:std_logic;
signal start_scan_cpu,start_scan_ff1,start_scan:std_logic;
signal start_sample_ack_ff1,start_sample_ack:std_logic;
signal start_scan_ack_ff1,start_scan_ack:std_logic;
signal fifo_full_scope,fifo_full_cpu,fifo_full_ff1:std_logic;
signal scope_rst,scope_rst_req:std_logic;
signal cha_data_sync,cha_data_scope:std_logic_vector(7 downto 0);
signal chb_data_sync,chb_data_scope:std_logic_vector(7 downto 0);
signal adc_clock,scope_clk:std_logic;
signal clk_div_en,clk_div_en_ack:std_logic;
signal data_sync,data_scope:std_logic_vector(15 downto 0);
component clk_gen is
    generic (div_factor_width: natural := 6);
    port (
        clkin: in std_logic;
        div_factor:in std_logic_vector(div_factor_width - 1 downto 0);
        div_en:in std_logic;
		div_en_ack: out std_logic;
        adc_clk: out std_logic;
        scope_clk: out std_logic;
        rst: in std_logic
    );
end component;
component scope_core is
	port(	cha_data: 			in std_logic_vector(7 downto 0);
			chb_data:			in std_logic_vector(7 downto 0);
			trigger_position:	in std_logic_vector(12 downto 0);
			trigger_voltage_level:in std_logic_vector(7 downto 0);
			trigger_mode:		in std_logic_vector(1 downto 0);
			trigger_source:		in std_logic;
			auto_trigger:		in std_logic;
			
			start_sample:		in std_logic;
			start_scan:			in std_logic;
			cha_fifo_rdreq:		in std_logic;
			cha_fifo_rdempty:	out std_logic;
			cha_fifo_rdfull:	out std_logic;
			cha_fifo_data:		out std_logic_vector(15 downto 0);
			chb_fifo_rdreq:		in std_logic;
			chb_fifo_rdempty:	out std_logic;
			chb_fifo_rdfull:	out std_logic;
			chb_fifo_data:		out std_logic_vector(15 downto 0);
			cur_state:			out std_logic_vector(7 downto 0);
			fifo_wrfull:		out std_logic;
			scope_clk:			in std_logic;
			ifclk:				in std_logic;
			rst:				in std_logic
	);
end component;
component adc_input_fifo
	PORT
	(
		data		: IN STD_LOGIC_VECTOR (15 DOWNTO 0);
		rdclk		: IN STD_LOGIC ;
		rdreq		: IN STD_LOGIC ;
		wrclk		: IN STD_LOGIC ;
		wrreq		: IN STD_LOGIC ;
		q		: OUT STD_LOGIC_VECTOR (15 DOWNTO 0)
	);
end component;
begin

    U1 : clk_gen generic map (div_factor_width => 6) port map (
        clkin => clk,
        div_factor => clk_div_factor,
        div_en => clk_div_en,
		div_en_ack => clk_div_en_ack,
        adc_clk => adc_clock,
        scope_clk => scope_clk,
        rst => scope_rst 
    );
    U3: adc_input_fifo port map(
        data => data_sync,
        rdclk => scope_clk,
        rdreq => '1',
        wrclk => adc_clock,
        wrreq => '1',
        q => data_scope
    );
    cha_data_scope <= data_scope(15 downto 8);
    chb_data_scope <= data_scope(7 downto 0);
    data_sync <= cha_data_sync & chb_data_sync;
	avs_s0_waitrequest <= '0';
	ins_irq0_irq <= '0'; -- TODO fifo_full with irq_en
    adc_clk <= adc_clock;
    process(clk,reset)
	begin
		if(reset = '1')then
			avs_s0_readdata <= (others => '0');
            clk_div_factor <= (others => '0');
			trigger_mode <= (others => '0');
			trigger_voltage_level <= (others => '0');
			trigger_source <= '0';
			trigger_position <= (others => '0');
			start_sample_cpu <= '0';
			start_scan_cpu <= '0';
			auto_trigger <= '0';
            start_sample_ack <= '0';
            start_sample_ack_ff1 <= '0';
            start_scan_ack <= '0';
            start_scan_ack_ff1 <= '0';
            clk_div_en <= '0';
            scope_rst <= '0';
            scope_rst_req <= '0';
			fifo_full_cpu <= '0';
			fifo_full_ff1 <= '0';
		elsif(clk = '1' and clk'event)then
			start_sample_ack <= start_sample_ack_ff1;
            start_sample_ack_ff1 <= start_sample;
            start_scan_ack <= start_scan_ack_ff1;
            start_scan_ack_ff1 <= start_scan;
			fifo_full_ff1 <= fifo_full_scope;
			fifo_full_cpu <= fifo_full_ff1;
            if(avs_s0_read = '1') then
				case avs_s0_address is
					when x"00" =>
						avs_s0_readdata(7 downto 0) <= scope_current_state;
						avs_s0_readdata(31 downto 8) <= (others=>'0');
					when x"04" =>
						avs_s0_readdata(0) <= fifo_full_cpu;
						avs_s0_readdata(31 downto 1) <= (others=>'0');
					when x"05" =>
						avs_s0_readdata(0) <= scope_rst_req;
						avs_s0_readdata(31 downto 1) <= (others=>'0');
					when others =>
						null;
				end case;
			elsif(avs_s0_write = '1') then
				case avs_s0_address is
					when x"01" =>
						auto_trigger <= avs_s0_writedata(15);
						trigger_source <= avs_s0_writedata(14);
						trigger_position <= avs_s0_writedata(12 downto 0);
					when x"02" =>
						clk_div_factor <= avs_s0_writedata(15 downto 10);
						trigger_mode <= avs_s0_writedata(9 downto 8);
						trigger_voltage_level <= avs_s0_writedata(7 downto 0);
					when x"03" =>
						start_sample_cpu <= avs_s0_writedata(0);
						start_scan_cpu <= avs_s0_writedata(1);				
					when x"05" =>
						scope_rst_req <= avs_s0_writedata(0);
					when x"06" =>
                        clk_div_en <= avs_s0_writedata(0);
                    when others =>
						null;
				end case;
			end if;
			if(scope_rst_req = '1') then
                clk_div_en <= '0';
                scope_rst <= '1';
				if(clk_div_en_ack = '0') then
					scope_rst_req <= '0';
				end if;
            else
                scope_rst <= '0';
			end if;
			
            if(start_sample_ack = '1') then
                start_sample_cpu <= '0';
            end if;
            if(start_scan_ack = '1') then
                start_scan_cpu <= '0';
            end if;
		end if;
	end process;
	process(scope_clk)
	begin
		if(scope_clk = '1' and scope_clk'event) then
			start_sample_ff1 <= start_sample_cpu;
			start_sample <= start_sample_ff1;
			start_scan_ff1 <= start_scan_cpu;
			start_scan <= start_scan_ff1;
		end if;
	end process;
    process(adc_clock)
    begin
        if(adc_clock = '1' and adc_clock'event)then
            cha_data_sync <= cha_data;
			chb_data_sync <= chb_data;
        end if;
    end process;

	U2: scope_core port map (
		cha_data => cha_data_scope,
		chb_data => chb_data_scope,
		trigger_position => trigger_position,
		trigger_voltage_level => trigger_voltage_level,
		trigger_mode => trigger_mode,
		trigger_source => trigger_source,
		auto_trigger => auto_trigger,

		start_sample => start_sample,
		start_scan => start_scan,
		cha_fifo_rdreq => cha_fifo_rdreq,
		cha_fifo_rdempty => cha_fifo_rdempty,
		cha_fifo_rdfull => open,
		cha_fifo_data => cha_fifo_data,
		chb_fifo_rdreq => chb_fifo_rdreq,
		chb_fifo_rdempty => chb_fifo_rdempty,
		chb_fifo_rdfull => open,
		chb_fifo_data => chb_fifo_data,
		cur_state => scope_current_state,
		fifo_wrfull => fifo_full_scope,
		scope_clk => scope_clk,
		ifclk => clk,
		rst => scope_rst or reset
	);
	
end architecture rtl; -- of scope_module
